using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

using Atomic.Libraries;
using Atomic.Libraries.Mathematics;
using Atomic.Structures;
using Atomic.Structures.Symmetries;

namespace Atomic.Interfaces.Atat
{
	public static class AtatSymmetryOperationParser
	{
		public static IEnumerable<SpaceGroupSymmetryOperation> FindSymmetries(Structure structure)
		{
			using (TempDirectory temp = new TempDirectory())
			{
				structure.Write(new FileInfo(Path.Combine(temp.Directory.FullName, "lat.in")));

				// Start corrdump process. Don't care about clusters here. IEEE 754 double-precision has up to 17 significant digits.
				Process p = new Process();
				try
				{
					p.StartInfo.RedirectStandardOutput = true;
					p.StartInfo.RedirectStandardError = true;
					p.StartInfo.UseShellExecute = false;
					p.StartInfo.FileName = "corrdump";
					p.StartInfo.Arguments = "-sym -sig=17";
					p.StartInfo.WorkingDirectory = temp.Directory.FullName;
					p.Start();
					p.WaitForExit();
				}
				finally
				{
					if (!p.HasExited)
					{
						p.Kill();
					}
				}

				return FindSymmetries(temp.Directory);
			}
		}

		public static IEnumerable<SpaceGroupSymmetryOperation> FindSymmetries(DirectoryInfo directory)
		{
			List<SpaceGroupSymmetryOperation> symmetries = new List<SpaceGroupSymmetryOperation>();

			using (StreamReader reader = new StreamReader(Path.Combine(directory.FullName, "sym.out")))
			{
				// Ignore first line.
				reader.ReadLine();

				while (!reader.EndOfStream)
				{
					// Each line contains one row of the rotation matrix.
					SpaceMatrix a = AtomicEnvironment.ParseSpaceMatrix(reader.ReadLine(), reader.ReadLine(), reader.ReadLine());
					reader.ReadLine();

					SpaceVector b = AtomicEnvironment.ParseSpaceVector(reader.ReadLine());
					reader.ReadLine();

					symmetries.Add(new SpaceGroupSymmetryOperation(null, a, b));
				}

				reader.Close();
			}

			return symmetries;
		}
	}
}
